package rs.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

/* Classe responsabile di inviare una richiesta a Last.fm e restituire la risposta */
public class Requester {

	/* Metodo pubblico per inviare una richiesta */
	public String send(String request) {				
		return attempt(0, request);
	}
	
	/* Si procede per tentativi, fino ad ottenere una risposta o un errore */
	private String attempt(int attempts, String request) {
		String response = "";
		
		try {
			URL url = new URL(request);
			HttpURLConnection connection = (HttpURLConnection)url.openConnection();
			connection.setRequestMethod("GET");

			InputStream is = connection.getInputStream();
			BufferedReader rd = new BufferedReader(new InputStreamReader(is));
			response = rd.readLine();
			rd.close();
			
			/* A volte capita di ottenere come risposta "" (stringa vuota) oppure """" (stringa con due doppi apici).
			 * In tal caso si ritorna un JSON di errore. */
			if (response.equals("") || response.equals("\"\"")) {
				response = "{\"error\":\"empty\"}";
			}
			
			/* Se invece si ottiene come risposta un errore, lo si gestisce nel seguente modo:
			 * 		se è un errore del tipo "try again", si procede con un altro tentativo 
			 * 		se si è raggiunto il massimo di tentativi o il code error è diverso da 4 (dati privati), si lancia un'eccezione */
			else if (response.substring(2,7).equals("error")) {
				int error = Integer.parseInt(response.substring(9,10));
				if ((error == 8 || error == 11 || error == 16) && attempts < TuningParameters.MAX_ATTEMPS)  {
					return attempt(attempts + 1, request);
				}
				else if (error != 4) {
					throw new RuntimeException("Error response: " + response + " for request: " + request);
				}
			}
			
		} catch (IOException ioe) {
			/* Se si ottiene un errore non grave si procede ad un'altra richiesta, altrimenti si ferma il processo */
			if ((ioe.getMessage().contains("Server returned HTTP response code: 503") || ioe.getMessage().contains("Connection timed out: connect")) && attempts < TuningParameters.MAX_ATTEMPS) {
				return attempt(attempts + 1, request);
			}
			else {
				ioe.printStackTrace();
				System.exit(0);
			}
		}
		
		return response;
	}

}
